#pragma once
#include <iostream>
#include <memory>
#include "socket.hpp"
#include "connection.hpp"
// #include "Inetaddr.hpp"
// #include "HandleConnection.hpp"

// 对所有套接字的行为进行管理的类

using namespace socket_namespace;

class Listener
{
public:
    Listener(uint16_t port)
        : _port(port), _listensocket(std::make_unique<TCPSocket>())
    {
        _listensocket->buildListenSocket(_port);
    }

    // ①
    int listensockfd()
    {
        return _listensocket->getsockfd();
    }

    void accepter(myConnection *conn)
    {
        while (true)
        {
            errno = 0;
            inetAddr addr;
            int code = 0;
            int socketfd = _listensocket->Accepter(&addr, &code);
            if (socketfd > 0)
            {
                // 成功获取一个套接字
                LOG(INFO, "获取链接成功，客户端：%s:%d, socketfd: %d\n", addr.IP().c_str(), addr.Port(), socketfd);
                
                // 注意：这里的代码只会在如下情况才会执行
                //      有新的客户端向服务器端发出了请求，
                //      才会将这个新创建的 用于双方通信的 socketfd添加到
                //      新创建的连接中
                conn->_R->AddConnection(socketfd, EPOLLIN|EPOLLET, addr, NormalConnection);
            }
            else
            {
                // 数据接收方在调用_listensocket->Accepter 之后
                // 用code 对数据退出码进行获取
                if (code == EWOULDBLOCK)
                {
                    LOG(INFO, "底层链接全部获取\n");
                    break;
                }
                // 退出码为中断
                else if (code == EINTR)
                {
                    continue;
                }
                else
                {
                    LOG(ERROR, "获取链接失败！\n");
                    break;
                }
            }
        }
    }

    ~Listener()
    {
    }

private:
    uint16_t _port;
    std::unique_ptr<Socket> _listensocket;
};
